/**
 * @Author: myweb
 * @Created: 2019-06-11 13:56
 * @Modifier: myweb
 * @Updated:
 * @Desc: quick-html 快速开发静态页 */
const express = require('express');
const quick = express();
const page = express();
const nunjucks = require('nunjucks');
const fs = require('fs');
const crypto = require('crypto');
const bodyParser = require('body-parser');
const os = require('os');
const compressing = require('compressing');
const sass = require('node-sass');
const filewatcher = require('filewatcher');
const watcher = filewatcher();
const ws = require('nodejs-websocket');

quick.use(bodyParser.urlencoded({extended: false}));

quick.use(express.static('./system/static'));


quick.all('*', function (req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "*");
    res.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
    res.header("Access-Control-Allow-Credentials", true);
    next()
});

quick.listen(3000, function () {
    console.log('服务器启动成功！3000');
});

/**
 * 读取文件公用函数
 * */
const readProject = (cbk, id) => {
    fs.readFile('./system/project.json', (err, data) => {
        if (id) {

            JSON.parse(data).forEach((e) => {
                if (e.id === id) {
                    cbk(e);
                }
            })
        } else {
            cbk(err, JSON.parse(data));
        }
    })
};
/**
 * 写文件公用函数
 * */
const saveProject = (data, cbk) => {
    let writeData = JSON.stringify(data);
    fs.writeFile('./system/project.json', writeData, 'utf-8', (err) => {
        cbk(err);
    })
};


/**
 * 根据hash删除文件
 * */
const removeSite = (id, cbk) => {
    readProject((err, data) => {
        if (!err) {
            data.forEach((e) => {
                if (e.id === id) {
                    if (fs.existsSync(e.path)) {
                        let _files = fs.readdirSync(e.path);
                        console.log(_files)
                        if (_files && _files.length == 0) {
                            fs.rmdirSync(e.path)
                        }
                    }
                    data.splice(data.indexOf(e), 1);
                    saveProject(data, (err) => {
                        cbk(err)
                    });
                }
            })
        } else {
            cbk(err)
        }
    })
};

/**
 * 时间格式化工具
 * */
const timeFormat = (time) => {
    let Time = time instanceof Date ? time : new Date(time);
    let fullYear = Time.getFullYear();
    let month = Time.getMonth() + 1;
    let date = Time.getDate();
    let hours = Time.getHours();
    let minutes = Time.getMinutes();
    let sec = Time.getSeconds();

    month = month > 9 ? month : '0' + month;
    date = date > 9 ? date : '0' + date;
    hours = hours > 9 ? hours : '0' + hours;
    minutes = minutes > 9 ? minutes : '0' + minutes;
    sec = sec > 9 ? sec : '0' + sec;
    return fullYear + '年' + month + '月 ' + date + '日 ' + hours + ":" + minutes + ":" + sec
};


/**
 * MD5
 * */
const MD = mingma => {
    let md5 = crypto.createHash('md5');
    return md5.update(mingma).digest('base64');
};
/**
 * HASH
 * */
const hash = str => {
    return crypto.createHash('md5').update(str).digest('hex');
};

/**
 * 复制模板文件到指定文件夹下
 * */

const copyFile = (formPath, toPath) => {
    if (fs.existsSync(toPath)) {
        console.log('路径存在，开始复制操作');
        fs.readdir(formPath, (err, data) => {
            data.forEach((e) => {
                let _from = formPath + '/' + e;
                let _to = toPath + '/' + e;
                if (fs.statSync(_from).isDirectory()) {
                    if (!fs.existsSync(_to)) {
                        fs.mkdirSync(_to)
                    }
                    copyFile(_from, _to);
                } else {
                    if (!fs.existsSync(_to)) {
                        fs.copyFileSync(_from, _to);
                    } else {
                        console.log(`文件${toPath}已存在，跳过`)
                    }
                }
            })
        })
    } else {
        console.log('目标路径不存在自动创建文件夹');
        fs.mkdirSync(toPath);
        copyFile(formPath, toPath);
    }
};

/**
 * 删除文件夹
 */
function rmFolder(path) {
    if (fs.existsSync(path)) {
        fs.readdirSync(path).forEach(function (file) {
            var curPath = path + "/" + file;
            if (fs.statSync(curPath).isDirectory()) {
                rmFolder(curPath);
            } else {
                fs.unlinkSync(curPath);
            }
        });
        fs.rmdirSync(path);
    }
}


/**
 * 获取项目信息
 * */
quick.get('/allprojects', (req, res) => {
    readProject((err, data) => {
        res.json({
            projects: data || [],
            homedir: os.homedir() + '/desktop'
        });
    });
});


/**
 * 新建完整项目
 * */
quick.post('/create', (req, res) => {
    console.log('新建站点');
    let date = new Date();
    let timeStamp = date.getTime();
    let dateString = timeFormat(date);
    let id = hash(String(timeStamp));
    let createPath = os.homedir() + '/desktop/' + req.body.name;

    if (fs.existsSync(createPath)) {
        res.json({
            status: false,
            msg: '创建失败，站点目录已存在'
        });
        return;
    }
    let _siteInfo = {
        name: req.body.name,
        id: id,
        timeStamp: timeStamp,
        date: dateString,
        path: createPath
    };

    readProject((err, data) => {
        if (!err) {
            data.push(_siteInfo);
            saveProject(data, err => {
                if (!err) {
                    fs.mkdirSync(createPath);
                    copyFile('./system/template', createPath);
                    fs.writeFileSync(createPath + '/siteInfo.json', JSON.stringify(_siteInfo), 'UTF-8');
                    res.json({
                        status: true,
                        msg: '新建成功'
                    })
                } else {
                    res.json({
                        status: false,
                        msg: err
                    })
                }
            })
        }
    });

});
/**
 * 删除站点
 **/
quick.post('/unlinksite', (req, res) => {
    let id = req.body.id;
    removeSite(id, (err) => {
        if (!err) {
            res.json({status: true, msg: '删除成功,如果关联目录为空，将自动删除该目录'})
        } else {
            res.json({status: false, msg: '删除失败'})
        }
    })
});
/**
 * 复制模板到站点目录
 **/
quick.post('/copytemplate', (req, res) => {
    copyFile('./system/template', req.body.path);
    res.json({
        status: true,
        msg: '复制成功,如果文件或目录已存在，将忽略'
    })
});
quick.post('/openSite', (req, res) => {
    createContainer(req.body.path);
    res.json({
        status: true,
        msg: '启动WEB服务器'
    })
});
/**
 * 站点控制面板
 */
quick.get('/siteinfo', (req, res) => {
    readProject((err, data) => {
        let _path = data[0].path;
        if (fs.existsSync(_path + '/html')) {
            let files = fs.readdirSync(data[0].path + '/html');
            let filesInfo = [];
            files.forEach((e) => {
                if (e.indexOf('.html') > -1) {
                    let _stat = fs.statSync(_path + '/html/' + e);
                    filesInfo.push({
                        fileName: e,
                        ctime: timeFormat(_stat.ctime),
                        mtime: timeFormat(_stat.mtime)
                    })
                }
            });
            createContainer(_path);
            res.json({
                status: true,
                data: data,
                filesInfo: filesInfo,
                msg: '站点数据已加载'
            })
        } else {
            res.json({
                status: false,
                msg: '站点目录不存在或为空！'
            })
        }

    }, req.query.id);
});

/***前台文件夹***/


page.listen(2019, () => {
    console.log('页面服务已运行');
});


function createContainer(path) {
    //加载静态资源目录
    const initSite = require('./system/extends');


    renderScss(path + '/src/scss', path + '/src/css');
    new initSite(page, path);

    watcher.add(path + '/html');
    watcher.add(path + '/html/layout');
    watcher.add(path + '/src/css');
    watcher.add(path + '/src/js');
    watcher.add(path + '/src/scss');
    watcher.on('change', function (file, stat) {
        if (file.indexOf('/src/scss') > -1) {
            console.log('scss update');
            renderScss(path + '/src/scss', path + '/src/css');
        }
        if (file.indexOf('/src/css') > -1) {
            console.log('css update')
        }
        if (file.indexOf('/src/js') > -1) {
            console.log('js update')
        }
        if (file.indexOf('/html') > -1) {
            console.log('HTML update')
        }
    });
}

/**
 * 打包生成静态页面函数
 * */
const dist = (id, cbk) => {
    readProject(data => {
        let _path = data.path;
        let htmlPath = _path + '/html';
        let distPath = _path + '/dist';
        let zipPath = _path + '/dist.zip';
        fs.existsSync(distPath) ? rmFolder(distPath) : 0;
        fs.mkdirSync(distPath);
        nunjucks.configure(htmlPath, {
            autoescape: true,
            express: quick,
            noCache: process.env.NODE_ENV !== 'production'
        });
        fs.readdir(htmlPath, (err, data) => {
            data.forEach(e => {
                if (e.indexOf('.html') > -1) {
                    nunjucks.render(htmlPath + '/' + e, {evn: 'product'}, (err, data) => {
                        fs.writeFileSync(distPath + '/' + e, data);
                    });
                }
            });
            fs.existsSync(zipPath) ? fs.unlinkSync(zipPath) : 0;
            copyFile(_path + '/src/', distPath);
            compressing.zip.compressDir(distPath, zipPath)
                .then(() => {
                    rmFolder(distPath);
                    cbk && cbk({status: true, path: _path + '/dist.zip'})
                })
                .catch(err => {
                    cbk && cbk({status: false, msg: err});
                });
        })
    }, id);
};

quick.get('/dist', (req, res) => {
    let id = req.query.id;
    dist(id, (data) => {
        if (data.status) {
            res.sendFile(data.path, (err) => {
                console.log(err);
            });
        } else {
            res.json(data)
        }
    });
});


/**
 *scss
 * */

const renderScss = (sourcePath, savePath) => {
    if (fs.existsSync(sourcePath)) {
        let pathArr = [];
        if (fs.statSync(sourcePath).isDirectory()) {
            let scssArr = fs.readdirSync(sourcePath);
            scssArr.forEach(e => {
                if (e.indexOf('.scss') > -1) {
                    pathArr.push({path: sourcePath + '/' + e, name: e.replace('scss', 'css')});
                }
            });
        } else {
            let _pathSplit = sourcePath.split('/');
            let name = _pathSplit[_pathSplit.length - 1];
            pathArr.push({path: sourcePath, name: name.replace('scss', 'css')});
        }

        if (pathArr.length) {
            pathArr.forEach(e => {
                let result = sass.renderSync({file: e.path});
                if (savePath && fs.existsSync(savePath)) {
                    fs.writeFileSync(savePath + '/' + e.name, result.css, 'utf-8');
                }
            });
        } else {
            return {
                status: false,
                msg: '目录下无SCSS文件'
            }
        }
    } else {
        return {
            status: false,
            msg: '路径不存在'
        }
    }
};

